﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;

namespace FaceIdentifier
{
    public class FaceApiImpl : FaceApi
    {
        private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(FaceApiImpl));
        private readonly Dictionary<string, PrivilegeInfo> _file = new Dictionary<string, PrivilegeInfo>();
        private string Repository = "人脸库";

        private IntPtr instance;

        public void UnInit()
        {
            if(instance != null)
            {
                BaiduFaceDll.UnInit(instance);
                instance = IntPtr.Zero;
            }
            
        }

        public void Add(string key, Bitmap bitmap)
        {
            AddBitmap(key, bitmap);
            _file.Clear();
        }

        public int FaceCount()
        {
            return _file.Count;
        }

        public PrivilegeInfo GetInfo(string key)
        {
            if (_file.Count == 0)
            {
                var files = Directory.GetFiles(Repository).Where(w => w.EndsWith("jpg"));
                foreach (var file in files)
                {
                    try
                    {
                        FileInfo fi = new FileInfo(file);
                        var fileNames = fi.Name.Replace(fi.Extension, "").Split('_');

                        PrivilegeInfo info = new PrivilegeInfo();
                        info.personSN = fileNames[0];
                        info.personName = fileNames[1];

                        _file.Add(info.personSN, info);
                    }
                    catch (Exception e)
                    {
                        Log.Error("添加人脸到对比库异常", e);
                    }
                }
            }
            PrivilegeInfo pi;
            _file.TryGetValue(key, out pi);
            return pi;
        }

        public void Init()
        {
            if(instance == null || instance == IntPtr.Zero)
            {
                Log.Info("开始初始化SDK");
                instance = BaiduFaceDll.Init();
                Log.Info("初始化SDK成功");
            }
        }

        public string Match(Bitmap bitmap)
        {
            Init();
            Log.Debug("正在识别");
            Stopwatch watch = Stopwatch.StartNew();
            var base64 = Bitmap2Base64(bitmap);
            Log.DebugFormat("base64 耗时:{0}",watch.ElapsedMilliseconds);

            if (string.IsNullOrEmpty(base64))
            {
                Log.Warn("base64为空");
                return null;
            }
            StringBuilder buffer = new StringBuilder(1000);
            BaiduFaceDll.Identifier(instance, base64, ref buffer);
            string result = buffer.ToString();
            Log.DebugFormat("Identifier 耗时:{0}", watch.ElapsedMilliseconds);
            if (string.IsNullOrEmpty(result))
            {
                Log.Warn("人脸识别动态库返回null");
                return null;
            }
            Log.InfoFormat("result {0}", result);

            JObject jobject = JObject.Parse(result);
            int errno = Convert.ToInt32(jobject["errno"]);
            //未检测到人
            if (errno != 0)
            {
                return null;
            }
            JArray results = (JArray)jobject["data"]["result"];
            foreach (JObject j in results)
            {
                string score = Convert.ToString(j["score"]);
                if (!string.IsNullOrEmpty(score) && Convert.ToDouble(score) > 70)
                {
                    return Convert.ToString(j["user_id"]);
                }
            }
            return "";
        }

        public void ReloadFace()
        {
            if (!Directory.Exists(Repository))
            {
                Log.InfoFormat("创建本地对比库:{0}", Repository);
                Directory.CreateDirectory(Repository);
            }

            Log.InfoFormat("加载人脸库图片列表", Repository);
            var files = Directory.GetFiles(Repository).Where(w => w.EndsWith("jpg"));
            foreach (var file in files)
            {
                try
                {
                    Log.InfoFormat("加载人脸库图片:{0}", file);
                    var fi = new FileInfo(file);
                    var name = fi.Name.Replace(fi.Extension, "");

                    using (var bitmap = new Bitmap(file))
                    {
                        var key = name.Split('_')[0];
                        AddBitmap(key, bitmap);
                    }

                }
                catch (Exception e)
                {
                    Log.Error("添加人脸到对比库异常", e);
                }
            }
            _file.Clear();
        }

        private void AddBitmap(string key, Bitmap bitmap)
        {
            Init();
            Log.InfoFormat("添加人脸到数据库:{0}", key);
            StringBuilder buffer = new StringBuilder(1000);
            BaiduFaceDll.UserDelete(instance, key,ref buffer);
            buffer.Clear();
            int i = BaiduFaceDll.UserAdd(instance, key, Bitmap2Base64(bitmap), ref buffer);
            Log.InfoFormat("user_add {0}", i);
            Log.InfoFormat("UserAdd result:{0}",buffer.ToString());
        }

        public void Remove(string key)
        {
            Init();
            StringBuilder buffer = new StringBuilder(1000);
            BaiduFaceDll.UserDelete(instance, key, ref buffer);
        }

        public string Bitmap2Base64(Bitmap bitmap)
        {
            if (bitmap == null || bitmap.Width == 0 || bitmap.Height == 0) return null;

            try
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    bitmap.Save(ms, ImageFormat.Jpeg);
                    byte[] bytes = new byte[ms.Length];
                    ms.Position = 0;
                    ms.Read(bytes, 0, bytes.Length);
                    return Convert.ToBase64String(bytes);
                }
            }
            catch (Exception)
            {

                return null;
            }
        }
    }

}
